using System;
using System.Collections.Specialized;
using System.Reflection;
using System.Web;
using System.Web.Security;

namespace Salient.Web.Administration
{
    public sealed class WebAdminMembershipProvider : MembershipProvider
    {
        public WebAdminRemotingManager RemotingManager
        {
            get { return (WebAdminRemotingManager) HttpContext.Current.Session["WebAdminRemotingManager"]; }
        }

        public override string ApplicationName
        {
            get { return (string) GetWebAdminMembershipProviderHelperProperty("ApplicationName"); }
            set { ; }
        }

        public override bool EnablePasswordRetrieval
        {
            get { return (bool) GetWebAdminMembershipProviderHelperProperty("EnablePasswordRetrieval"); }
        }

        public override bool EnablePasswordReset
        {
            get { return (bool) GetWebAdminMembershipProviderHelperProperty("EnablePasswordReset"); }
        }

        public override bool RequiresQuestionAndAnswer
        {
            get { return (bool) GetWebAdminMembershipProviderHelperProperty("RequiresQuestionAndAnswer"); }
        }

        public override bool RequiresUniqueEmail
        {
            get { return (bool) GetWebAdminMembershipProviderHelperProperty("RequiresUniqueEmail"); }
        }

        public override int MaxInvalidPasswordAttempts
        {
            get { return (int) GetWebAdminMembershipProviderHelperProperty("MaxInvalidPasswordAttempts"); }
        }

        public override int PasswordAttemptWindow
        {
            get { return (int) GetWebAdminMembershipProviderHelperProperty("PasswordAttemptWindow"); }
        }

        public override MembershipPasswordFormat PasswordFormat
        {
            get { return (MembershipPasswordFormat) GetWebAdminMembershipProviderHelperProperty("PasswordFormat"); }
        }

        public override int MinRequiredPasswordLength
        {
            get { return (int) GetWebAdminMembershipProviderHelperProperty("MinRequiredPasswordLength"); }
        }

        public override int MinRequiredNonAlphanumericCharacters
        {
            get { return (int) GetWebAdminMembershipProviderHelperProperty("MinRequiredNonAlphanumericCharacters"); }
        }

        public override string PasswordStrengthRegularExpression
        {
            get { return (string) GetWebAdminMembershipProviderHelperProperty("PasswordStrengthRegularExpression"); }
        }

        public object CallWebAdminMembershipProviderHelperMethod(string methodName, object[] parameters,
                                                                 Type[] paramTypes)
        {
            object returnObject = null;
            object tempObject = null;

            tempObject = RemotingManager.ConfigurationHelperInstance;
            if (tempObject != null)
            {
                string typeFullName = WebAdminRemotingManager.AssemblyVersionString;
                Type tempType = Type.GetType(typeFullName);

                BindingFlags allBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
                MethodInfo method = tempType.GetMethod("CallMembershipProviderMethod", allBindingFlags);
                if (method != null)
                {
                    var newParameters = new object[] {methodName, parameters, paramTypes};
                    var returnArrayObj = (object[]) method.Invoke(tempObject, newParameters);
                    if (returnArrayObj != null)
                    {
                        returnObject = returnArrayObj[0];
                    }
                }
            }

            return returnObject;
        }

        public object[] CallWebAdminMembershipProviderHelperMethodOutParams(string methodName, object[] parameters,
                                                                            Type[] paramTypes)
        {
            var returnObjectArray = new object[0];

            object tempObject = RemotingManager.ConfigurationHelperInstance;
            if (tempObject != null)
            {
                string typeFullName = WebAdminRemotingManager.AssemblyVersionString;
                Type tempType = Type.GetType(typeFullName);

                BindingFlags allBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
                MethodInfo method = tempType.GetMethod("CallMembershipProviderMethod", allBindingFlags);
                if (method != null)
                {
                    var newParameters = new object[] {methodName, parameters, paramTypes};
                    var returnArrayObj = (object[]) method.Invoke(tempObject, newParameters);
                    if (returnArrayObj != null)
                    {
                        returnObjectArray = returnArrayObj;
                    }
                }
            }

            return returnObjectArray;
        }

        public object GetWebAdminMembershipProviderHelperProperty(string propertyName)
        {
            object returnObject = null;
            object tempObject = null;
            tempObject = RemotingManager.ConfigurationHelperInstance;
            if (tempObject != null)
            {
                string typeFullName = WebAdminRemotingManager.AssemblyVersionString;
                Type tempType = Type.GetType(typeFullName);

                BindingFlags allBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
                MethodInfo method = tempType.GetMethod("GetMembershipProviderProperty", allBindingFlags);
                if (method != null)
                {
                    var newParameters = new object[] {propertyName};
                    returnObject = method.Invoke(tempObject, newParameters);
                }
            }

            return returnObject;
        }

        public override bool ChangePassword(string name, string oldPwd, string newPwd)
        {
            return
                (bool)
                CallWebAdminMembershipProviderHelperMethod("ChangePassword", new object[] {name, oldPwd, newPwd},
                                                           new[]
                                                               {typeof (string), typeof (string), typeof (string)});
        }

        public override bool ChangePasswordQuestionAndAnswer(string name, string password, string newPwdQuestion,
                                                             string newPwdAnswer)
        {
            return
                (bool)
                CallWebAdminMembershipProviderHelperMethod("ChangePasswordQuestionAndAnswer",
                                                           new object[] {name, password, newPwdQuestion, newPwdAnswer},
                                                           new[]
                                                               {
                                                                   typeof (string), typeof (string), typeof (string),
                                                                   typeof (string)
                                                               });
        }

        public override MembershipUser CreateUser(string username,
                                                  string password,
                                                  string email,
                                                  string passwordQuestion,
                                                  string passwordAnswer,
                                                  bool isApproved,
                                                  object providerUserKey,
                                                  out MembershipCreateStatus status)
        {
            MembershipUser TempUser = null;
            status = MembershipCreateStatus.InvalidUserName;
            string typeFullName = "System.Web.Security.MembershipCreateStatus&, " +
                                  typeof (HttpContext).Assembly.GetName();
            Type tempType = Type.GetType(typeFullName);

            object[] returnAndOutParams = CallWebAdminMembershipProviderHelperMethodOutParams("CreateUser",
                                                                                              new[]
                                                                                                  {
                                                                                                      username, password
                                                                                                      ,
                                                                                                      email,
                                                                                                      passwordQuestion,
                                                                                                      passwordAnswer,
                                                                                                      isApproved,
                                                                                                      providerUserKey,
                                                                                                      status
                                                                                                  },
                                                                                              new[]
                                                                                                  {
                                                                                                      typeof (string),
                                                                                                      typeof (string),
                                                                                                      typeof (string),
                                                                                                      typeof (string),
                                                                                                      typeof (string),
                                                                                                      typeof (bool),
                                                                                                      typeof (object),
                                                                                                      tempType
                                                                                                  });
            if (returnAndOutParams != null)
            {
                TempUser = (MembershipUser) returnAndOutParams[0];
                status = (MembershipCreateStatus) returnAndOutParams[8];
            }

            if (status != MembershipCreateStatus.Success)
            {
                return null;
            }
            else
            {
                return TempUser;
            }
        }

        public override bool DeleteUser(string name, bool deleteAllRelatedContent)
        {
            return
                (bool)
                CallWebAdminMembershipProviderHelperMethod("DeleteUser", new object[] {name, deleteAllRelatedContent},
                                                           new[] {typeof (string), typeof (bool)});
        }

        public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
        {
            totalRecords = 0;
            var TempList =
                (MembershipUserCollection)
                CallWebAdminMembershipProviderHelperMethod("GetAllUsers",
                                                           new object[] {pageIndex, pageSize, totalRecords},
                                                           new[]
                                                               {
                                                                   typeof (int), typeof (int),
                                                                   Type.GetType("System.Int32&")
                                                               });
            var NewList = new MembershipUserCollection();
            foreach (MembershipUser TempItem in TempList)
            {
                var NewUser = new MembershipUser(Name,
                                                 TempItem.UserName,
                                                 TempItem.ProviderUserKey,
                                                 TempItem.Email,
                                                 TempItem.PasswordQuestion,
                                                 TempItem.Comment,
                                                 TempItem.IsApproved,
                                                 TempItem.IsLockedOut,
                                                 TempItem.CreationDate,
                                                 TempItem.LastLoginDate,
                                                 TempItem.LastActivityDate,
                                                 TempItem.LastPasswordChangedDate,
                                                 TempItem.LastLockoutDate);

                NewList.Add(NewUser);
            }

            return NewList;
        }

        public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize,
                                                                  out int totalRecords)
        {
            totalRecords = 0;
            var TempList =
                (MembershipUserCollection)
                CallWebAdminMembershipProviderHelperMethod("FindUsersByEmail",
                                                           new object[]
                                                               {emailToMatch, pageIndex, pageSize, totalRecords},
                                                           new[]
                                                               {
                                                                   typeof (string), typeof (int), typeof (int),
                                                                   Type.GetType("System.Int32&")
                                                               });
            var NewList = new MembershipUserCollection();
            foreach (MembershipUser TempItem in TempList)
            {
                var NewUser = new MembershipUser(Name,
                                                 TempItem.UserName,
                                                 TempItem.ProviderUserKey,
                                                 TempItem.Email,
                                                 TempItem.PasswordQuestion,
                                                 TempItem.Comment,
                                                 TempItem.IsApproved,
                                                 TempItem.IsLockedOut,
                                                 TempItem.CreationDate,
                                                 TempItem.LastLoginDate,
                                                 TempItem.LastActivityDate,
                                                 TempItem.LastPasswordChangedDate,
                                                 TempItem.LastLockoutDate);

                NewList.Add(NewUser);
            }

            return NewList;
        }

        public override int GetNumberOfUsersOnline()
        {
            return (int) CallWebAdminMembershipProviderHelperMethod("GetNumberOfUsersOnline", new object[] {}, null);
        }

        public override string GetPassword(string name, string answer)
        {
            return
                (string)
                CallWebAdminMembershipProviderHelperMethod("GetPassword", new object[] {name, answer},
                                                           new[] {typeof (string), typeof (string)});
        }

        public override MembershipUser GetUser(string name, bool userIsOnline)
        {
            var TempUser =
                (MembershipUser)
                CallWebAdminMembershipProviderHelperMethod("GetUser", new object[] {name, userIsOnline},
                                                           new[] {typeof (string), typeof (bool)});
            var NewUser = new MembershipUser(Name,
                                             TempUser.UserName,
                                             TempUser.ProviderUserKey,
                                             TempUser.Email,
                                             TempUser.PasswordQuestion,
                                             TempUser.Comment,
                                             TempUser.IsApproved,
                                             TempUser.IsLockedOut,
                                             TempUser.CreationDate,
                                             TempUser.LastLoginDate,
                                             TempUser.LastActivityDate,
                                             TempUser.LastPasswordChangedDate,
                                             TempUser.LastLockoutDate);

            return NewUser;
        }

        public override string GetUserNameByEmail(string email)
        {
            return
                (string)
                CallWebAdminMembershipProviderHelperMethod("GetUserNameByEmail", new object[] {email},
                                                           new[] {typeof (string)});
        }

        public override string ResetPassword(string name, string answer)
        {
            return
                (string)
                CallWebAdminMembershipProviderHelperMethod("ResetPassword", new object[] {name, answer},
                                                           new[] {typeof (string), typeof (string)});
        }

        public override void UpdateUser(MembershipUser user)
        {
            string typeFullName = "System.Web.Security.MembershipUser, " +
                                  typeof (HttpContext).Assembly.GetName();
            ;
            Type tempType = Type.GetType(typeFullName);

            CallWebAdminMembershipProviderHelperMethod("UpdateUser", new object[] {user},
                                                       new[] {tempType});
        }

        public override bool ValidateUser(string name, string password)
        {
            return
                (bool)
                CallWebAdminMembershipProviderHelperMethod("ValidateUser", new object[] {name, password},
                                                           new[] {typeof (string), typeof (string)});
        }

        public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
        {
            return
                (MembershipUser)
                CallWebAdminMembershipProviderHelperMethod("GetUser", new[] {providerUserKey, userIsOnline},
                                                           new[] {typeof (object), typeof (bool)});
        }

        public override bool UnlockUser(string name)
        {
            return
                (bool)
                CallWebAdminMembershipProviderHelperMethod("UnlockUser", new object[] {name},
                                                           new[] {typeof (string)});
        }

        public override void Initialize(string name, NameValueCollection config)
        {
            if (String.IsNullOrEmpty(name))
            {
                name = "WebAdminMembershipProvider";
            }

            base.Initialize(name, config);
        }

        public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize,
                                                                 out int totalRecords)
        {
            totalRecords = 0;
            var TempList =
                (MembershipUserCollection)
                CallWebAdminMembershipProviderHelperMethod("FindUsersByName",
                                                           new object[]
                                                               {usernameToMatch, pageIndex, pageSize, totalRecords},
                                                           new[]
                                                               {
                                                                   typeof (string), typeof (int), typeof (int),
                                                                   Type.GetType("System.Int32&")
                                                               });
            var NewList = new MembershipUserCollection();
            foreach (MembershipUser TempItem in TempList)
            {
                var NewUser = new MembershipUser(Name,
                                                 TempItem.UserName,
                                                 TempItem.ProviderUserKey,
                                                 TempItem.Email,
                                                 TempItem.PasswordQuestion,
                                                 TempItem.Comment,
                                                 TempItem.IsApproved,
                                                 TempItem.IsLockedOut,
                                                 TempItem.CreationDate,
                                                 TempItem.LastLoginDate,
                                                 TempItem.LastActivityDate,
                                                 TempItem.LastPasswordChangedDate,
                                                 TempItem.LastLockoutDate);

                NewList.Add(NewUser);
            }

            return NewList;
        }
    }
}